package com.hw.disruptor.eventProducer;

import com.hw.disruptor.event.LongEvent;
import com.lmax.disruptor.RingBuffer;

/**
 * @program: disruptor-quickstart
 * @author: hewei
 * @date: 2023-07-06 15:57
 * <p>
 *     自定义消息发布者
 * 如果我们使用RingBuffer.next()获取一个事件槽，那么一定要发布对应的事件。如果不能发布事件，那么就会引起Disruptor状态的混乱。
 * 尤其是在多个事件生产者的情况下会导致事件消费者失速，从而不得不重启应用才能会恢复。
 * Disruptor 3.0提供了lambda式的API。这样可以把一些复杂的操作放在Ring Buffer，
 * 所以在Disruptor3.0以后的版本最好使用Event Publisher或者Event Translator(事件转换器)来发布事件。
 * </p>
 **/
public class LongEventProducer {

    private final RingBuffer<LongEvent> RING_BUFFER;

    public LongEventProducer(RingBuffer<LongEvent> ringBuffer) {
        this.RING_BUFFER = ringBuffer;
    }

    /**
     * pushData用来发布事件，每调用一次就发布一次事件事件,它的参数会通过事件传递给消费者
     * 发布事件最少需要两步：
     * 1.获取下一个事件槽，
     * 2.发布事件（发布事件的时候要使用try/finnally保证事件一定会被发布）
     */

    public void publishData(Long data) {
        //可以把ringBuffer看做一个事件队列，那么next就是得到下面一个事件槽
        long sequence = RING_BUFFER.next();
        try {
            //用上面的索引取出一个空的事件用于填充
            LongEvent event = RING_BUFFER.get(sequence);
            event.setValue(data);
        } finally {
            //发布事件
            RING_BUFFER.publish(sequence);
        }
    }
}